@startuml


package "Main Process" {
    class MainProcess {
        +MainProcess()
        +void run()
    }

    MainProcess --> config
    MainProcess --> usersList
    MainProcess --> LoginDialog
    MainProcess --> MainWindow
}

"Main Process" ..> "Login and Registration" : <<import>>
"Main Process" ..> "Users" : <<import>>
"Main Process" ..> "Main Window" : <<import>>

package "Users" {
	class user {
		+std::string _login
		+std::string _salt
		+CipherAlgorithm _cipher_algorithm_
		-Botan::secure_vector<std::uint8_t> _hashedPassword
		+std::filesystem::path _dataPath
		+std::filesystem::path _totpPath
		+user()
		+user(const std::string& line)
		+void setHashedPassword(const std::string& hashedPassword)
		+void setHashedPassword(const Botan::secure_vector<uint8_t>& hashedPassword)
		+std::filesystem::path getDataPath() const
		+std::filesystem::path getTotpPath() const
		+CipherAlgorithm getAlgorithm() const
		+bool compare_hashes(const Botan::secure_vector<uint8_t>& hash1) const
		+Botan::SymmetricKey generatePass() const
		-std::string getHash() const
		+friend std::string to_string(const user& user)
	}

	class usersList {
		-std::vector<user> _users
		+usersList(const std::filesystem::path& path, QObject *parent = nullptr)
		+iterator begin()
		+iterator end()
		+const_iterator begin() const
		+const_iterator end() const
		+user& operator[](int index)
		+void saveInFile(const std::filesystem::path& path)
		+bool empty() const
		+slot void appendUser(const user& user)
	}

	enum CipherAlgorithm
	usersList "1" *-- "0..*" user
	user o-- CipherAlgorithm
}
"Users" ..> "Utils": <<import>>

package "Login and Registration" {
    class LoginDialog {
        -QLabel *labelUsername
        -QLabel *labelPassword
        -QLabel *labelUserCorrect
        -QComboBox *comboUsername
        -QLineEdit *editPassword
        -QDialogButtonBox *buttons
        -QPushButton *addUserButton
        -QPushButton *closeButton
        -usersList& list
        +LoginDialog(usersList &list, QWidget *parent = nullptr)
        +void setUsername(QString &username)
        +void setPassword(QString &password)
        +void setUpGUI()
        +void slotAcceptLogin()
        +void addUser()
        +signal void acceptLogin(const user& user)
    }

    class registrationDialog {
        -QLabel *labelUsername
        -QLabel *labelPassword
        -QLabel *label2ndPassword
        -QLabel *labelUserCorrect
        -QLabel *passwordErrorLabel
        -QLineEdit *editPassword
        -QLineEdit *edit2ndPassword
        -QLineEdit *editUserName
        -QDialogButtonBox *buttons
        -QComboBox *algorithmCombo
        -bool passwordsAreSame
        -bool passwordIsSecure
        -PopUp *_pop_up
        +registrationDialog(QWidget *parent = nullptr)
        +void checkPasswords()
        +void createUser()
        +void isPasswordSecure(const QString& password)
        +void generatePassword()
        +void setUpGUI()
        +signal void sendUser(const user& user)
        +signal void sendDataCopied()
    }

    LoginDialog --> registrationDialog
    LoginDialog o-- usersList
    LoginDialog ..> user
    registrationDialog ..> user
}
"Login and Registration" ..> "Users" : <<import>>

package "Crypto" {

    class Cipher {
        -std::unique_ptr<Botan::RandomNumberGenerator> rng
        -std::unique_ptr<Botan::Cipher_Mode> cipher
        -Botan::InitializationVector iv
        +Cipher()
        +bool chooseCipher(CipherAlgorithm algorithm, Botan::Cipher_Dir direction)
        +void setIV(const Botan::secure_vector<uint8_t>& iv)
        +void saveIVinFile(const std::string& filename) const
        +void saveIVInByteArray(Botan::secure_vector<uint8_t>& data) const
        +bool loadIV(const std::string& filename, std::size_t ivSize)
        +void generateIvWithSaving(std::size_t size)
        +Botan::InitializationVector generateIV(std::size_t size)
        +Botan::secure_vector<uint8_t> encrypt(const Botan::SymmetricKey& key, const Botan::secure_vector<uint8_t>& plaintext) const
        +Botan::secure_vector<uint8_t> decrypt(const Botan::SymmetricKey& key, const Botan::secure_vector<uint8_t>& ciphertext) const
        +Botan::secure_vector<uint8_t> updateEncryption(const Botan::SymmetricKey& key, const Botan::InitializationVector& newIV,
                                                       const Botan::secure_vector<uint8_t>& plaintext, CipherAlgorithm algorithm = CipherAlgorithm::Kuznyechik_CBC)
    }

    class cipherManager {
        -std::shared_ptr<Cipher> _cipher
        -Botan::SymmetricKey key
        -Botan::Cipher_Dir direction
        -CipherAlgorithm algos
        -Botan::secure_vector<uint8_t> path
        +cipherManager(CipherAlgorithm algorithm, Botan::SymmetricKey key, std::filesystem::path fileNameIV)
        +cipherManager(CipherAlgorithm algorithm, Botan::SymmetricKey key, const Botan::secure_vector<uint8_t>& iv)
        +~cipherManager()
        +void setPath(std::filesystem::path fileNameIV)
        +void setPath(Botan::secure_vector<uint8_t> fileNameIV)
        +Botan::secure_vector<uint8_t> encrypt(const Botan::secure_vector<uint8_t> &plaintext, bool saveIV)
        +Botan::secure_vector<uint8_t> decrypt(const Botan::secure_vector<uint8_t> &plaintext, bool saveIV)
        +Botan::secure_vector<uint8_t> updateDecryption(const Botan::InitializationVector& newIV, const Botan::secure_vector<uint8_t> &plaintext)
        +std::shared_ptr<Cipher> getCipher()
        +Botan::InitializationVector generateIV()
    }

    class cryptomanager {
        -cipherManager manager
        -std::fstream file
        -CipherAlgorithm algorithm
        -Botan::SymmetricKey key
        -std::filesystem::path path
        +cryptomanager(const std::filesystem::path& path, CipherAlgorithm algorithm, Botan::SymmetricKey key)
        +SecureDataMap getData()
        +void WriteData(SecureDataMap& map)
        +~cryptomanager()
    }

    class SecureDataMap {
        -std::vector<SecureDataMapItem> data
        -std::shared_ptr<cipherManager> manager
        +SecureDataMap(std::shared_ptr<cipherManager> manager)
        +SecureDataMap(const SecureDataMap& map) = default
        +void addItemBySecureDataItem(SecureDataMapItem&& item)
        +void addItemBySecureDataItem(const SecureDataMapItem& item)
        +void addItemByStrings(std::string service, std::string login, std::string unecryptedPassword, std::string unecryptedData)
        +std::vector<SecureDataMapItem>::const_iterator getData(const std::string& login) const
        +std::vector<SecureDataMapItem>::iterator getDataViaLoginAndServiceName(const std::string &login, const std::string &service)
        +void clearData()
        +std::size_t count() const
        +void deleteItemByLogin(std::string login)
        +void deleteItem(std::vector<SecureDataMapItem>::const_iterator iter)
        +std::vector<SecureDataMapItem>::iterator begin()
        +std::vector<SecureDataMapItem>::iterator end()
        +std::vector<SecureDataMapItem>::const_iterator begin() const
        +std::vector<SecureDataMapItem>::const_iterator end() const
        +std::shared_ptr<cipherManager> getCipherManager() const
        +Botan::secure_vector<uint8_t> writeMapInSecureVector()
    }

    class SecureDataMapItem {
        -QString _service_name
        -QString _login
        -Botan::secure_vector<uint8_t> _password
        -Botan::secure_vector<uint8_t> _notes
        -std::weak_ptr<cipherManager> _manager
        -bool _isEmpty
        +SecureDataMapItem()
        +SecureDataMapItem(QString service_name, QString login, Botan::secure_vector<uint8_t> password, Botan::secure_vector<uint8_t> notes, std::weak_ptr<cipherManager> manager)
        +SecureDataMapItem(std::string service_name, std::string login, Botan::secure_vector<uint8_t> password, Botan::secure_vector<uint8_t> notes, std::weak_ptr<cipherManager> manager)
        +SecureDataMapItem(const std::string& data, std::weak_ptr<cipherManager> manager)
        +SecureDataMapItem(const SecureDataMapItem& item)
        +QString getDecryptedData(DataType type) const
        +std::string getEncryptedData(DataType type) const
        +void setDecryptedData(DataType type, const QString& el)
        +void setEncryptedData(DataType type, const Botan::secure_vector<uint8_t>& el)
        +void setManager(std::weak_ptr<cipherManager> manager)
        +void clear()
        +void reDecryptData(const Botan::InitializationVector& newIv)
        +bool empty() const
    }
	enum CipherAlgorithm
	enum DataType
    cipherManager --> Cipher
    Cipher -> CipherAlgorithm
    SecureDataMapItem ..> DataType
    SecureDataMap "1" *-- "0..*" SecureDataMapItem
    SecureDataMap "1" --> "1" cipherManager
    cryptomanager --> cipherManager
    cryptomanager --> CipherAlgorithm
}
"Crypto" ..> "Utils": <<import>>

package "TOTP" {
    class TOTPManager {
        -QString filepath
        -Botan::SymmetricKey encryptionKey
        -std::vector<TOTP> totps
        -std::string algos
        +TOTPManager(const std::filesystem::path& filepath, CipherAlgorithm algorithm, const Botan::SymmetricKey& encryptionKey, QObject* parent = nullptr)
        +const std::vector<TOTP>& getTOTPs() const
        +void saveTOTPs()
        +void loadTOTPs()
        +void addTOTP(const TOTP& totp)
        +void deleteTOTP(const TOTP& totp)
        -QByteArray encrypt(const QByteArray& plaintext)
        -QByteArray decrypt(const QByteArray& ciphertext)
    }

    struct TOTP {
        +QString label
        +Botan::SymmetricKey key
        +QString algorithm
        +int digits
        +int period
        +std::chrono::system_clock::time_point creation_time
        +TOTP(const QString& label, const Botan::SymmetricKey& key, const QString& algorithm, int digits, int period)
    }


	enum CipherAlgorithm
    TOTPManager o-- TOTP
    TOTPManager --> CipherAlgorithm
}
"TOTP" ..> "Crypto": <<import>>
"TOTP" ..> "Utils": <<import>>

package "Data Display" {
    class accountDataDialog {
        -QLineEdit* _serviceNameEdit
        -QLineEdit* _loginEdit
        -QLineEdit* _passwordEdit
        -QPlainTextEdit* _secureNoteEdit
        -QLabel* _serviceNameLabel
        -QLabel* _loginLabel
        -QLabel* _passwordLabel
        -QLabel* _secureNoteLabel
        -QLabel* _passwordWarning
        -QPushButton* _generatePasswordButton
        -QDialogButtonBox* _buttonBox
        -std::shared_ptr<cipherManager> _manager
        -std::shared_ptr<SecureDataMapItem> _item
        -PopUp* _pop_up
        -ClipboardWatcher& _clipboard_watcher

        +accountDataDialog(ClipboardWatcher& clipboard_watcher, QWidget *parent = nullptr, const std::shared_ptr<cipherManager>& manager = nullptr)
        +accountDataDialog(ClipboardWatcher& clipboard_watcher, QWidget *parent = nullptr, SecureDataMapItem* account = nullptr)
        +void sendData(const SecureDataMapItem &user)
        +void sendDataCopied()
        +void showPass()
        +void updateData()
        +void createData()
        +void generatePassword()
        +void isPasswordSecure(const QString& password)
        +bool eventFilter(QObject *obj, QEvent *event)
        -bool checkLineEditsNonEmpty()
    }

    class ClickableLabel {
        +ClickableLabel(QWidget *parent = nullptr)
        +void mousePressEvent(QMouseEvent *event)
        +signal void clicked()
    }

    class TOTPItemWidget {
        -TOTP m_totp
        -QProgressBar *progressBar
        -ClickableLabel *passwordLabel
        -QTimer *timer
        +TOTPItemWidget(const TOTP& totp, QWidget *parent = nullptr)
        +TOTP getTOTP() const
        +void updateProgress()
        +QString getPasswrodLabel()
        +signal void passwordCopied(QString)
        +signal void deleteRequested(const TOTP&)
        +slot void sendCopySignal()
        +slot void onDeleteClicked()
    }

    class TOTPConfigWindow {
        -QLineEdit *keyInput
        -QComboBox *algorithmCombo
        -QComboBox *digitsCombo
        -QLineEdit *periodInput
        -QLineEdit *nameInput
        +TOTPConfigWindow(QWidget *parent = nullptr)
        +signal void configSaved(const QString& label, const Botan::SymmetricKey& key, const QString& algorithm, int digits, int period)
        +slot void saveConfig()
    }

    class TOTPListWidget {
        -QListWidget *totpListWidget
        -ClipboardWatcher &_clipboard_watcher
        +TOTPListWidget(ClipboardWatcher &clipboard_watcher, QWidget *parent = nullptr)
        +void addTOTP(const TOTP& totp)
        +slot void copyTOTPToClipboard(QListWidgetItem *item)
        +slot void copyTOTPToClipboard(QString password)
        +slot void onTOTPDeleteRequested(const TOTP &totp)
        +signal void PasswordCopied()
        +signal void totpDeleted(const TOTP&)
    }

    class TOTPWindow {
        -TOTPListWidget *totpListWindow
        -PopUp *popup
        -ClipboardWatcher &_clipboard_wather
        +TOTPWindow(ClipboardWatcher &clipboard_watcher, QWidget *parent = nullptr)
        +TOTPWindow(const std::vector<TOTP>& totps, ClipboardWatcher &clipboard_watcher, QWidget *parent = nullptr)
        +signal void addedTotp(const TOTP&)
        +signal void deleteTotp(const TOTP&)
        +slot void addTOTP()
        +slot void addTOTPToList(const QString& label, const Botan::SymmetricKey& key, const QString& algorithm, int digits, int period)
        +slot void openPopupWindow()
        +slot void fillTotpListWindow(const std::vector<TOTP>& totps)
        +slot void onTotpDeleted(const TOTP& totp)
    }
	enum DataType
	TOTPWindow *-- TOTPListWidget
	TOTPWindow *-- TOTPConfigWindow
	TOTPWindow o-- PopUp
	TOTPWindow o-- ClipboardWatcher
	TOTPListWidget *-- TOTPItemWidget
	TOTPListWidget o-- ClipboardWatcher
	TOTPItemWidget *-- TOTP
	TOTPItemWidget *-- ClickableLabel
	accountDataDialog ..> DataType
    accountDataDialog o-- ClipboardWatcher
    accountDataDialog --> SecureDataMapItem
    accountDataDialog --> cipherManager
    accountDataDialog o-- PopUp
}
"Data Display" ..> "Crypto" : <<import>>
"Data Display" ..> "Utils" : <<import>>

package "Main Window" {
    class MainWindow {
        +MainWindow(config& config, QWidget *parent = nullptr)
        +~MainWindow()
        +void closeEvent(QCloseEvent *event)
        +void setUser(const user& user)
        +void on_saveButton_clicked()
        +void addDataToSecureDataMap(const SecureDataMapItem& item)
        +void openAccWindow()
        +void showClearedPopup()
        +void on_totpButton_clicked()
        +void addTOTP(const TOTP& totp)
        +void deleteTOTP(const TOTP& totp)
        +void showContextMenu(const QPoint &pos)
        +void trayIconActivated(QSystemTrayIcon::ActivationReason reason)
        +void openTotp()
        +void fillTable()
        +void createContextMenu()
        +void copyPassword()
        +void deleteRow()
        +void createTrayIcon()

        -QSystemTrayIcon *trayIcon
        -QMenu *trayIconMenu
        -QMenu *tableContextMenu
        -QAction *copyPasswordAction
        -QAction *deleteRowAction
        -QAction *minimizeAction
        -QAction *restoreAction
        -QAction *quitAction
        -QAction *openTotpAction
        -Ui::MainWindow *ui
        -std::unique_ptr<SecureDataMap> _sdm
        -std::unique_ptr<cryptomanager> _manag
        -std::unique_ptr<TOTPManager> _totpManager
        -config& _config
        -PopUp *_popup
        -user _user
        -ClipboardWatcher _clipboard_watcher
        -bool _data_clicked
        -accountDataDialog *_dataDialog
        -TOTPWindow *_totpDialog
    }


    MainWindow *-- config
    MainWindow *-- cryptomanager
    MainWindow *-- SecureDataMap
    MainWindow *-- TOTPManager
    MainWindow *-- accountDataDialog
    MainWindow *-- ClipboardWatcher
    MainWindow *-- TOTPWindow
    MainWindow *-- PopUp
    MainWindow *-- user
}
"Main Window" ..> "Crypto" : <<import>>
"Main Window" ..> "TOTP" : <<import>>
"Main Window" ..> "Data Display" : <<import>>
"Main Window" ..> "Users" : <<import>>
"Main Window" ..> "Utils" : <<import>>


package "Utils" {
	class ClipboardWatcher {
        -QTimer timer
        -QString clipboardHash

        +ClipboardWatcher(QObject *parent = nullptr)
        +void setClipboardData(const QString &data)
        +void startTimer()
        +void clipboardCleared() : signal
        -QString generateHash(const QString &data)
        +bool eventFilter(QObject *obj, QEvent *event)
        -void clearClipboard()
    }
	class PopUp {
		-QLabel label
		-QGridLayout layout
		-QPropertyAnimation animation
		-float popupOpacity
		-QTimer *timer
		-QRect currentGeometry
		+PopUp(QRect currentGeometry, QWidget *parent = 0)
		+void paintEvent(QPaintEvent *event)
		+void setPopupText(const QString& text)
		+void show()
		+slot void hideAnimation()
		+slot void hide()
		+void setPopupOpacity(float opacity)
		+float getPopupOpacity() const
	}

	class config {
        -std::filesystem::path appDir
        -std::filesystem::path usersFile
        -std::filesystem::path pathToUsersSecrets
        +config(const std::string& currentAppFile)
        +void setUsersFiles(const std::filesystem::path& path)
        +void setPathToUsersSecrets(const std::filesystem::path& path)
        +void saveConfig()
        +std::filesystem::path getUsersFile() const
        +std::filesystem::path getPathToUsersSecrets() const
    }

    enum CipherAlgorithm {
        Kuznyechik_CBC
        Magma_CBC
        AES_256_CBC
    }

    enum DataType {
        SERVICE_NAME
        LOGIN
        PASSWORD
        NOTES
    }
}


@enduml
